﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Athena.RouteAddress.Implementations
{
    public abstract class BaseServiceMultipleRouteManager : IServiceMultipleRouteManager
    {

        public event EventHandler<ServiceMultipleRouteEventArgs> created;
        public event EventHandler<ServiceMultipleRouteEventArgs> changed;
        public event EventHandler<ServiceMultipleRouteEventArgs> removed;

        protected readonly IRouteDescriptorChanger routeDescriptorChanger;

        public BaseServiceMultipleRouteManager(IRouteDescriptorChanger routeDescriptorChanger)
        {
            this.routeDescriptorChanger = routeDescriptorChanger;
        }

        public event EventHandler<ServiceMultipleRouteEventArgs> Created {
            add { created += value; }
            remove { created -= value; }
        }

        public event EventHandler<ServiceMultipleRouteEventArgs> Removed {
            add { removed += value; }
            remove { removed -= value; }
        }

        public event EventHandler<ServiceMultipleRouteEventArgs> Changed {
            add { changed += value; }
            remove { changed -= value; }
        }

        protected void OnCreated(params ServiceMultipleRouteEventArgs[] args)
        {
            if (created == null)
            {
                return;
            }
            foreach (var arg in args)
            {
                created(this, arg);
            }
        }

        protected void OnChanged(params ServiceMultipleRouteEventArgs[] args)
        {
            if (changed == null)
            {
                return;
            }
            foreach (var arg in args)
            {
                changed(this, arg);
            }
        }

        protected void OnRemoved(params ServiceMultipleRouteEventArgs[] args)
        {
            if (removed == null)
            {
                return;
            }
            foreach (var arg in args)
            {
                removed(this, arg);
            }
        }
        async Task<IEnumerable<ServiceMultipleRoute>> IServiceMultipleRouteManager.GetServiceMultipleRouteAsync()
        {
            var serviceMultipleRouteDescriptors = await GetServiceMultipleRouteDescriptorAsync();

            var serviceMultipleRoutes = new List<ServiceMultipleRoute>();
            foreach (var item in serviceMultipleRouteDescriptors)
            {
                serviceMultipleRoutes.Add(new ServiceMultipleRoute()
                {
                    ServiceDescriptor = item.ServiceDescriptor,
                    ServiceRoutes = item.RouteDescriptors.Select(serviceRouteDescriptor => new ServiceRoute()
                    {
                        CorrelationId = serviceRouteDescriptor.CorrelationId,
                        Routes = serviceRouteDescriptor.RouteDescriptors.Select(routeDescriptor => (Route)routeDescriptorChanger.CreateRoute(routeDescriptor))
                    })
                });
            }
            return serviceMultipleRoutes;
        }

        Task IServiceMultipleRouteManager.SetServiceMultipleRoutesAsync(IEnumerable<ServiceMultipleRoute> serviceMultipleRoutes)
        {
            var serviceMultipleRouteDescriptors = new List<ServiceMultipleRouteDescriptor>();
            foreach (var item in serviceMultipleRoutes)
            {
                serviceMultipleRouteDescriptors.Add(new ServiceMultipleRouteDescriptor()
                {
                    ServiceDescriptor = item.ServiceDescriptor,
                    RouteDescriptors = item.ServiceRoutes.Select(serviceRoute => new ServiceRouteDescriptor()
                    {
                        CorrelationId = serviceRoute.CorrelationId,
                        RouteDescriptors = serviceRoute.Routes.Select(route => routeDescriptorChanger.CreateRouteDescriptor(route))
                    })
                });
            }
            return SetServiceMultipleRouteDescriptorAsync(serviceMultipleRouteDescriptors);
        }



        public abstract Task ClearAsync();

        public abstract Task<IEnumerable<ServiceMultipleRouteDescriptor>> GetServiceMultipleRouteDescriptorAsync();

        public abstract Task SetServiceMultipleRouteDescriptorAsync(IEnumerable<ServiceMultipleRouteDescriptor> serviceMultipleRouteDescriptors);


    }
}
